/**
 * @author: mattwang@tencent.com
 * @date: 2012-10-16
 */

#ifndef __LBFGS_TRAINER_H__
#define __LBFGS_TRAINER_H__

#include "type_def.h"
#include "loader/class_loader.h"

class LBFGSTrainer {
public:
	void train(int max_iter = 100, double eps = 1E-05);

	size_t n_class;
	size_t n_test_data;          	//
	size_t n_train_data;          		//
	size_t n_theta;

	std::vector<SampleVector> *train_data;
	std::vector<int> *train_data_class;
	std::vector<double> *train_data_weight;
	std::vector<SampleVector> *test_data;
	std::vector<int> *test_data_class;
	std::vector<double> *test_data_weight;
	vector<vector<pair<size_t, size_t> > >*param_map;
	double *sigma2;

	double *theta_all;

private:
	void init_trainer();
	double heldout_accuracy() const;

	struct featid_hasher {
		size_t operator()(const pair<size_t, size_t>& p) const {
			return p.first + p.second;
		}
	};

	int calc_function(int dim, double *x, double &f, double *gradient, int correct);

	double global_data_weight;
	double *local_observed_expects;
	double *global_observed_expects;
	double *local_gradient;

	size_t eval(SampleVector sample, vector<double>& probs) const;
};

#endif // __LBFGS_H__
